package org.mozhu.zufang.admin.web.controller;

import org.mozhu.mboot.core.social.SocialUserInfo;
import org.mozhu.mboot.core.web.security.HttpSecurityHolder;
import org.mozhu.zufang.system.account.entity.User;
import org.mozhu.zufang.system.account.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.web.ProviderSignInUtils;
import org.springframework.social.security.SocialAuthenticationToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.ServletWebRequest;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/social")
public class SocialController {

    @Autowired
    private ProviderSignInUtils providerSignInUtils;

    @Autowired
    private UserService userService;

    @GetMapping("/register")
    public String socialRegister(HttpServletRequest request, Model model) {
        Connection<?> connection = providerSignInUtils.getConnectionFromSession(new ServletWebRequest(request));
        if (connection == null) {
            return "redirect:/login";
        }
        SocialUserInfo socialUserInfo = new SocialUserInfo();
        socialUserInfo.setProviderId(connection.getKey().getProviderId());
        socialUserInfo.setProviderUserId(connection.getKey().getProviderUserId());
        socialUserInfo.setNickname(connection.getDisplayName());
        socialUserInfo.setHeadImg(connection.getImageUrl());
        model.addAttribute("socialUserInfo", socialUserInfo);
        return "social/register";
    }

    @PostMapping("/register")
    public String register(HttpServletRequest request, Model model,
                           @RequestParam("loginName") String loginName,
                           @RequestParam("email") String email,
                           @RequestParam("password") String password
    ) {
        Connection<?> connection = providerSignInUtils.getConnectionFromSession(new ServletWebRequest(request));
        if (connection == null) {
            return "redirect:/login";
        }
        User existUser = userService.findByLoginName(loginName);
        if (existUser != null) {
            model.addAttribute("error", "User of loginName[" + loginName + "] already exist");
            return socialRegister(request, model);
        }
        existUser = userService.findByEmail(email);
        if (existUser != null) {
            model.addAttribute("error", "User of email[" + email + "] already exist");
            return socialRegister(request, model);
        }
        User user = new User();
        user.setLoginName(loginName);
        user.setEmail(email);
        user.setPlainPassword(password);
        userService.encryptPassword(user);
        userService.save(user);

        providerSignInUtils.doPostSignUp(loginName, new ServletWebRequest(request));

        AuthenticationManager authenticationManager = HttpSecurityHolder.get().getHttpSecurity().getSharedObject(AuthenticationManager.class);
        Authentication authentication = authenticationManager.authenticate(new SocialAuthenticationToken(connection, null));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return "redirect:/";
    }

    @RequestMapping(value = "/register/validate")
    @ResponseBody
    public Object validate(@RequestParam(value = "field") String field, @RequestParam(value = "fieldValue") String fieldValue) {
        if ("loginName".equals(field)) {
            User user = userService.findByLoginName(fieldValue);
            return user == null;
        }

        if ("email".equals(field)) {
            User user = userService.findByEmail(fieldValue);
            return user == null;
        }
        return null;
    }
}
